package com.yonyou.pmclouds.organization.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoInsertMultiProcessor;
import com.yonyou.pmclouds.basecom.bp.template.MultiInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleDeleteBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.exception.ConcurrentOperationException;
import com.yonyou.pmclouds.basecom.lock.AutoReleaseLockUtil;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.SqlUtil;
import com.yonyou.pmclouds.organization.entity.OrgAndRoleVO;
import com.yonyou.pmclouds.organization.entity.OrgConst;
import com.yonyou.pmclouds.organization.entity.OrganizationVO;
import com.yonyou.pmclouds.organization.entity.RoleDistributeVO;
import com.yonyou.pmclouds.organization.mapper.OrgAndRoleMapper;
import com.yonyou.pmclouds.organization.mapper.OrganizationMapper;
import com.yonyou.pmclouds.organization.mapper.RoleDistributeMapper;
import com.yonyou.pmclouds.organization.process.OrgInsertCheckProcessor;
import com.yonyou.pmclouds.organization.process.RoleDistributeCheckProcessor;
import com.yonyou.pmclouds.organization.rmiitf.OrganizationMaintain;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;


@Service(version = ApplicationConsts.APPLICATION_VERSION,interfaceClass= OrganizationMaintain.class)
public class OrganizationMaintainImpl implements OrganizationMaintain {
    @Autowired
    private OrganizationMapper mapper;
    @Autowired
    private OrgAndRoleMapper roleMapper;
    @Autowired
    private RoleDistributeMapper roleDistributeMapper;

    public static final String LOCK_PREFIX = "organization";

    @Override
    public OrganizationVO[] insertOrgs(OrganizationVO[] organizationVOS) throws BusinessException {
        if(ArrayUtils.isEmpty(organizationVOS)){
            return new OrganizationVO[0];
        }
        if(!AutoReleaseLockUtil.addAutoReleaseLock(LOCK_PREFIX + organizationVOS[0].getPkTenant())) {
            throw new ConcurrentOperationException();
        }
        MultiInsertBpTemplate<OrganizationVO> bp = new MultiInsertBpTemplate<>(mapper);
        //更新审计信息
        bp.addBeforeProcessor(new AuditInfoInsertMultiProcessor<OrganizationVO>());
        //编码唯一性校验
        bp.addBeforeProcessor(new OrgInsertCheckProcessor(mapper));
        return bp.insert(organizationVOS);
    }

    @Override
    public OrganizationVO[] updateOrg(OrganizationVO[] organizationVOS, String[] updateFields) throws BusinessException {
        if(ArrayUtils.isEmpty(organizationVOS)){
            return new OrganizationVO[0];
        }
        SingleUpdateBpTemplate<OrganizationVO> bp = new SingleUpdateBpTemplate<>(mapper, updateFields);
        for(OrganizationVO vo : organizationVOS){
            if(vo != null){
                bp.update(vo);
            }
        }
        return organizationVOS;
    }

    @Override
    public OrganizationVO deleteOrg(OrganizationVO organizationVO) throws BusinessException {
        if(organizationVO == null){
            return null;
        }
        if(!AutoReleaseLockUtil.addAutoReleaseLock(LOCK_PREFIX + organizationVO.getPkTenant())) {
            throw new ConcurrentOperationException();
        }
        SingleDeleteBpTemplate<OrganizationVO> bp = new SingleDeleteBpTemplate<>(mapper);

        return bp.delete(organizationVO);
    }

    @Override
    public OrganizationVO[] update4Enable(OrganizationVO[] organizationVOS) throws BusinessException {
        if(ArrayUtils.isEmpty(organizationVOS))
            return new OrganizationVO[0];

        List<String> codes = new ArrayList<>();
        for(OrganizationVO vo : organizationVOS){
            if(vo != null) codes.add(vo.getScode());
        }

        SingleUpdateBpTemplate<OrganizationVO> bp = new SingleUpdateBpTemplate<>(mapper, new String[]{OrganizationVO.ENABLE_STATE});
        for(OrganizationVO vo : organizationVOS){
            if(vo != null){
                vo.setEnableState(OrgConst.ENABLE_STATE);
                bp.update(vo);
            }
        }
        return organizationVOS;
    }
    @Override
    public OrganizationVO[] update4Disable(OrganizationVO[] organizationVOS, Set<String> recordRole) throws BusinessException {
        if(ArrayUtils.isEmpty(organizationVOS))
            return new OrganizationVO[0];

        List<String> codes = new ArrayList<>();
        for(OrganizationVO vo : organizationVOS){
            if(vo != null) codes.add(vo.getScode());
        }
        orgIsDistributeCheck(organizationVOS, recordRole);
        SingleUpdateBpTemplate<OrganizationVO> bp = new SingleUpdateBpTemplate<>(mapper, new String[]{OrganizationVO.ENABLE_STATE});
        for(OrganizationVO vo : organizationVOS){
            if(vo != null){
                vo.setEnableState(OrgConst.DISABLE_STATE);
                bp.update(vo);
            }
        }

        return organizationVOS;
    }

    /**
     * 分配组织给角色
     */
    @Override
    public void update4Distribute(OrgAndRoleVO[] orgRoleVOS) throws BusinessException {
        if(ArrayUtils.isEmpty(orgRoleVOS)) return;
        List<OrgAndRoleVO> insertVOS = new ArrayList<>();
        List<String> deleteOrgs = new ArrayList<>();
        String pkRole = null;
        boolean isTenantDelete = false;
        for(OrgAndRoleVO vo : orgRoleVOS){
            if(vo == null) continue;
            vo.setPkTenant(RuntimeEnvironment.getTenantId());
            if(vo.getIsDistributed() != null && vo.getIsDistributed()) insertVOS.add(vo);
            else {
                if(vo.getIsTenant().equals("Y")){
                    isTenantDelete = true;
                }else{
                    deleteOrgs.add(vo.getPkOrganization());
                }
                if(pkRole == null) pkRole = vo.getPkRole();
            }
        }
        MultiInsertBpTemplate<OrgAndRoleVO> insertBp = new MultiInsertBpTemplate<>(roleMapper);
        insertBp.addBeforeProcessor(new AuditInfoInsertMultiProcessor<OrgAndRoleVO>());
        if(insertVOS.size() > 0){
            insertBp.insert(insertVOS.toArray(new OrgAndRoleVO[0]));
        }
        OrgAndRoleVO[] deleteVOS = null;
        if(deleteOrgs.size() > 0 || isTenantDelete){
            if(deleteOrgs.size() > 0) {
                deleteVOS = roleMapper.getListByOrgAndRole(RuntimeEnvironment.getTenantId(), SqlUtil.getSqlIn(deleteOrgs.toArray(new String[0])), pkRole);
            }
            if(isTenantDelete){
                OrgAndRoleVO[] tenantRoles = roleMapper.getTenantRoleList(RuntimeEnvironment.getTenantId(), SqlUtil.getSqlIn(new String[]{pkRole}));
                deleteVOS = ArrayUtils.addAll(deleteVOS, tenantRoles);
            }
        }
        SingleDeleteBpTemplate<OrgAndRoleVO> deleteBp = new SingleDeleteBpTemplate<>(roleMapper);
        if(ArrayUtils.isNotEmpty(deleteVOS)){
            for(OrgAndRoleVO vo : deleteVOS){
                if(vo != null) deleteBp.delete(vo);
            }
        }

    }

    /**
     * 取消分配
     */
    @Override
    public void update4CancelDistribute(String pkRole) throws BusinessException {
        if(StringUtils.isEmpty(pkRole)) return;
        OrgAndRoleVO[] deleteVOS = roleMapper.getOrgByRole(RuntimeEnvironment.getTenantId(), SqlUtil.getSqlIn(new String[]{pkRole}));
        SingleDeleteBpTemplate<OrgAndRoleVO> deleteBp = new SingleDeleteBpTemplate<>(roleMapper);
        if(ArrayUtils.isNotEmpty(deleteVOS)){
            for(OrgAndRoleVO vo : deleteVOS){
                if(vo != null) deleteBp.delete(vo);
            }
        }

        RoleDistributeVO[] roleDistributeVOS = roleDistributeMapper.getByPkRoles(RuntimeEnvironment.getTenantId(), SqlUtil.getSqlIn(new String[]{pkRole}));
        SingleDeleteBpTemplate<RoleDistributeVO> bp = new SingleDeleteBpTemplate<>(roleDistributeMapper);
        if(ArrayUtils.isNotEmpty(roleDistributeVOS)){
            for(RoleDistributeVO vo : roleDistributeVOS){
                if(vo != null) bp.delete(vo);
            }
        }
    }

    @Override
    public RoleDistributeVO[] insertRoles(RoleDistributeVO[] roleDistributeVOS) throws BusinessException {
        if(ArrayUtils.isEmpty(roleDistributeVOS)){
            return new RoleDistributeVO[0];
        }
        MultiInsertBpTemplate<RoleDistributeVO> bp = new MultiInsertBpTemplate<>(roleDistributeMapper);
        //更新审计信息
        bp.addBeforeProcessor(new AuditInfoInsertMultiProcessor<RoleDistributeVO>());
        bp.addBeforeProcessor(new RoleDistributeCheckProcessor(roleDistributeMapper));
        return bp.insert(roleDistributeVOS);
    }


    private void orgIsDistributeCheck(OrganizationVO[] organizationVOS, Set<String> recordRole) throws BusinessException {
        List<String> pkOrgs = new ArrayList<>();
        for(OrganizationVO vo : organizationVOS){
            if(vo != null) pkOrgs.add(vo.getPkOrganization());
        }
        OrgAndRoleVO[] roleVOS = roleMapper.getRoleByOrg(RuntimeEnvironment.getTenantId(), SqlUtil.getSqlIn(pkOrgs.toArray(new String[0])));
        if(ArrayUtils.isEmpty(roleVOS)){
            return;
        }
        Set<String> recordOrg = new HashSet<>();
        StringBuffer msg = new StringBuffer();
        msg.append("组织已经分配，无法禁用！已经分配的组织包含：");
        for(OrgAndRoleVO vo : roleVOS){
            if(vo != null && StringUtils.isNotEmpty(vo.getPkRole()) && recordRole.contains(vo.getPkRole())){
                recordOrg.add(vo.getPkOrganization());
            }
        }
        if(recordOrg.size() > 0){
            for(OrganizationVO orgVO : organizationVOS){
                if(orgVO != null && recordOrg.contains(orgVO.getPkOrganization())){
                    msg.append(orgVO.getScode() + ",");
                }
            }
            msg.deleteCharAt(msg.length() - 1);
            msg.append("。");
            throw new BusinessException(msg.toString());
        }
    }

}
